/***************************************
 * Created by Junyi Tang.
 *
 * 2009.1.14 
 *
 * GPL v2
 * */

/*
 * =====================================================================================
 *
 *       Filename:  main.c
 *
 *    Description:  translate string (en->zh-CN 效果比较好^_^)
 *
 *        Version:  1.0
 *        Created:  01/13/1009 03:11:43 PM
 *       Revision:  none
 *       Compiler:  gcc
 *               :  GPL v2
 *
 * =====================================================================================
 */

#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <error.h>

#include <glib.h>

#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>

#define BUFFER_SIZE	4096

char result[BUFFER_SIZE];
int result_flag = -1;


const char *langs[] = {"en", "zh-CN", "zh-TW"};
const char *utf8s[] = {"zh-CN", "zh-TW"};
void usage(void)
{
    printf("\033[31mGT en,zh-CN \"China\"\n\033[00m");
    exit(1);
}

//回调函数
size_t write_data (void *ptr, size_t size, size_t nmemb, void *stream)	
{
  FILE *fp;	//定义FILE类型指针
  int written;
  
  if(0 == (get_content((char *)ptr)) )
	  result_flag = 1;

  fp = fopen("/dev/null", "w");
  written = fwrite (ptr, size, nmemb, (FILE *) fp);
  fclose(fp);

  return written;
}


//解析返回的html页面，获取翻译结果
int get_content(char *html_content)
{
  char *ss_start = NULL;
  char *se_end = NULL;

  char *ss = "<div id=result_box dir=\"ltr\">";
  char *se = "</div>";

  ss_start = strstr(html_content, ss);
  
  if(ss_start != NULL)
  {
  	se_end = strstr(ss_start, se);
	ss_start += strlen(ss);
	strncat(result, ss_start, se_end - ss_start); 
  	return 0;
  }

  return -1;

}


/************************************************
 * 把字符串进行URL编码。
 * 输入：
 * str: 要编码的字符串
 * strSize: 字符串的长度。这样str中可以是二进制数据
 * result: 结果缓冲区的地址
 * resultSize:结果地址的缓冲区大小(如果str所有字符都编码，该值为strSize*3)
 * 返回值：
 * >0: result中实际有效的字符长度，
 * 0: 编码失败，原因是结果缓冲区result的长度太小
 ***********************************************/ 
int URLEncode(const char* str, const int strSize, char* result, const int resultSize) 
{
	int i;
	int j = 0; /* for result index */
	char ch;

	if ((str == NULL) || (result == NULL) || (strSize <= 0) || (resultSize <= 0)) {
		return 0;
	}

	for (i=0; (i<strSize) && (j<resultSize); i++) {
		ch = str[i];
		if ((ch >= 'A') && (ch <= 'Z')) {
			result[j++] = ch;
		} else if ((ch >= 'a') && (ch <= 'z')) {
			result[j++] = ch;
		} else if ((ch >= '0') && (ch <= '9')) {
			result[j++] = ch;
		} else if(ch == ' ' || ch == '\n' || ch == '\r'|| ch == '\t'){
			result[j++] = '+';
		} else {
			if (j + 3 < resultSize) {
				sprintf(result+j, "%%%02X", (unsigned char)ch);
				j += 3;
			} else {
				return 0;
			}
		}
	}

	result[j] = '\0';
	return j;
} 

int translate_engine(char *inputText, const char *head_code, const char *tail_code)
{
  char urlstr[BUFFER_SIZE];
  char langpair[256];
  char engineUrl[256];
  CURL *curl;
  
  memset(urlstr, 0, BUFFER_SIZE);
	
  int inputTextLen = sizeof(char) * 3 * strlen(inputText);
  char *inputText_encoded = malloc(inputTextLen);
  
  sprintf(langpair, "%s|%s", head_code, tail_code);
  sprintf(engineUrl, "%s", "http://translate.google.cn/translate_t");
  //sprintf(engineUrl, "%s", "http://translate.google.com/translate_t");

  URLEncode(inputText, strlen(inputText), inputText_encoded, inputTextLen + 2);
  sprintf(urlstr, "%s?text=%s&langpair=%s#", engineUrl, inputText_encoded, langpair);
  //sprintf(urlstr, "%s?hl=%s#%s|%s", engineUrl, head_code, langpair, inputText_encoded);

  //fprintf(stdout, "urlstr: %s\n", urlstr);

  curl_global_init (CURL_GLOBAL_ALL);
  curl = curl_easy_init ();
#ifdef _DEBUG
  curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
#endif
  curl_easy_setopt (curl, CURLOPT_URL, urlstr);
  curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, write_data);	
  curl_easy_perform (curl);
  curl_easy_cleanup (curl);

  return 0;
}


/* 
 ***************************************************************************************
 *  @Name       : int lang_check(const char *code)
 *
 *  @Purpose    : check code valid or not
 *  @Returns    : 
 *  @Parameters : 
 *  @Remarks    : 
 * =====================================================================================
 */
int lang_check(const char *code, const int flag)
{
    int L;
    const char **tmp;
    if(flag == 1)
    {
        L = sizeof(langs)/sizeof(langs[0]);
        tmp = langs;
    }
    else
    {
        L = sizeof(utf8s)/sizeof(utf8s[0]);
        tmp = utf8s;
    }

    int i;
    for(i = 0; i < L; i++)
    {
        if(!strcmp(tmp[i], code)) return 1;
    }
    return 0;
}
/* 
 ***************************************************************************************
 *  @Name       : parse_code
 *
 *  @Purpose    : get from and to code
 *  @Returns    : NULL
 *  @Parameters : 
 *  @Remarks    : remember free from & to 's memory
 * =====================================================================================
 */
int parse_code(const char *codes, char **from, char **to)
{
    int len = 0;
    const char *tmp = codes;
    while(*tmp != '\0')
    {
        if(*tmp== ',') 
        {
            break;
        }
        ++tmp;
        ++len;
    }

    // from code
    *from = malloc(sizeof(char) * (len + 1));
    bzero(*from, len + 1);
    strncpy(*from, codes, len);
    if(!lang_check(*from, 1)) return 0;
#ifdef DEBUG
    fprintf(stdout, "from code:%s\n", *from);
#endif
    ++tmp;
    ++len;

    // to code
    *to = malloc(sizeof(char) * (strlen(codes) - len + 1));
    bzero(*to, strlen(codes) - len + 1);
    strcpy(*to, tmp);
#ifdef DEBUG
    fprintf(stdout, "to code:%s\n", *to);
#endif
    if(!lang_check(*to, 1)) return 0;
    return 1;
}

int main(int argc, char **argv)
{
    if(argc != 3)
    {
        usage();
    }

    char *from_code;
    char *to_code;

    // 
    if(!parse_code(argv[1], &from_code, &to_code))
    {
        fprintf(stderr, "\033[31mPlease check your code.\n\033[00m");
    }

#ifdef DEBUG
    fprintf(stdout, "tocode: %s : %d\n", to_code, strlen(to_code));
    fprintf(stdout, "fromcode: %s : %d\n", from_code, strlen(from_code));
#endif

    //////
    char *ask = argv[2];
    
    translate_engine(ask, from_code, to_code);

    // code 
    int utf8_text_len = strlen(result);
    char *utf8_text = malloc(utf8_text_len);
    if(lang_check(to_code, 2))
    {
	utf8_text = g_convert(result, -1, "utf-8", "GB2312", NULL, NULL, NULL);
    }
    else
    {
		sprintf(utf8_text, "%s", result);
    }
    fprintf(stdout, "%s\n", utf8_text);

    free(from_code);
    free(to_code);
    free(utf8_text);
    return 0;
}



